package com.zhdl.network.service.impl;

import cn.hutool.core.util.HexUtil;
import com.google.common.eventbus.Subscribe;
import com.project.command.faq.queues.data.ControlInstructionPerformData;
import com.project.command.instruction.service.InstructionSendService;
import com.project.command.instruction.strategy.process.data.AfterStrategyParam;
import com.project.common.constant.Dic;
import com.zhdl.common.eventbus.center.EventBusCenter;
import com.zhdl.common.util.CRCUtils;
import com.zhdl.modules.tools.CommonCallback;
import com.zhdl.modules.tools.PublicTools;
import com.zhdl.network.electricityMeter.APUPackageBuild;
import com.zhdl.network.electricityMeter.DeviceInfo;
import com.zhdl.network.electricityMeter.LiveData;
import com.zhdl.network.electricityMeter.ThresholdInfo;
import com.zhdl.network.service.WaterMeterService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.project.common.constant.Dic.HAND_AFTER_DEFAULT_SERVICE;
import static com.zhdl.network.servertcp.ModBusTcpServerHandler.ipMaps;

@Slf4j
@Service
public class WaterMeterServiceImpl implements WaterMeterService {

    @Autowired
    private InstructionSendService instructionSendService;

    @Override
    public void sendCmd(String id, String cmd) {
        String substring = cmd.substring(8);
        String crc = CRCUtils.getCRC(substring);
        cmd += crc;
        //客户端通信地址, 串口为数字, 网口为ip+端口       数据来源 : port_comm 或 port_socket 表
        //instruction.setPortKey("192.168.4.4:502");
        /* 遍历Ip来发送指令 */
        for (String s : ipMaps.keySet()) {
            log.info(s);
            if (id.equals(s)){
                ControlInstructionPerformData data = new ControlInstructionPerformData();
                data.setInstruction(HexUtil.decodeHex(cmd));
                data.setPortKey("0.0.0.0:5555");
                data.setDstAdd(ipMaps.get(s).getIp());
                data.setProtocols(Dic.HAND_MODBUS_RTU_ANALYSIS);
                data.setAfterInstructionName(HAND_AFTER_DEFAULT_SERVICE);
                data.setDataBit(10);
                data.setChain(cmd);
                instructionSendService.sendToClient(data);
                break;
            }
        }

        //设置协议  数据来源 : protocols 表
//        instruction.setProtocols(ModbusAnalysis.MODBUS_TCP_ANALYSIS);

    }

    public void init(){
        /*
            初始化时-注册广播用户
         */
        EventBusCenter.getEventBus().register(this);
    }

    public String highToLow(String data){
        String s1 = data.substring(0,2);
        String s2 = data.substring(2,4);
        return s2 + s1;
    }

    public short stringToHex(String data){
        Integer i = Integer.parseInt(data, 16);
        return i.shortValue();
    }

    public String stringToAscii(String data){

        StringBuilder output = new StringBuilder("");

        for (int i = 0; i < data.length(); i += 2) {
            String str = data.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        log.info(output.toString());
        return output.toString();
    }

    public String webParam = "";

    public DeviceInfo deviceInfo = new DeviceInfo();
    public LiveData liveData = new LiveData();
    public ThresholdInfo thresholdInfo = new ThresholdInfo();

    @Subscribe
    public void eventReceiver(AfterStrategyParam resp) {
        List<byte[]> bytes = resp.getNewData();
        byte[] bytes1 = bytes.get(0);
        String s = HexUtil.encodeHexStr(bytes1);
        if (s.equals("7777772e7573722e636e")){
            log.info("客户端心跳不做处理");
        }else{
            String substring = s.substring(36, 40);
            if (substring.equals("0100")) {
                //设备信息查询结果
                String idList = s.substring(40, 52);
                for (int i = 0; i < idList.length()/2; i++) {
                    switch (i){
                        case 0 ->{
                            deviceInfo.setID_1(String.valueOf(HexUtil.hexToInt(idList.substring(2*i,i*2+2))));
                        }
                        case 1 ->{
                            deviceInfo.setID_2(String.valueOf(HexUtil.hexToInt(idList.substring(2*i,i*2+2))));
                        }
                        case 2 ->{
                            deviceInfo.setID_3(String.valueOf(HexUtil.hexToInt(idList.substring(2*i,i*2+2))));
                        }
                        case 3 ->{
                            deviceInfo.setID_4(String.valueOf(HexUtil.hexToInt(idList.substring(2*i,i*2+2))));
                        }
                        case 4 ->{
                            deviceInfo.setID_5(String.valueOf(HexUtil.hexToInt(idList.substring(2*i,i*2+2))));
                        }
                        case 5 ->{
                            deviceInfo.setID_6(String.valueOf(HexUtil.hexToInt(idList.substring(2*i,i*2+2))));
                        }
                        default ->
                                log.info("ID"+(i+1)+"_"+HexUtil.hexToInt(idList.substring(2*i,i*2+2)));
                    }
                }
                String s0 = s.substring(52, 56);
                String s1 = highToLow(s0);
                Integer i = Integer.parseInt(s1, 16);
                deviceInfo.setCurrentInfo(String.valueOf(i.shortValue()));
                log.info("额定电流"+ i.shortValue());
                webParam = String.valueOf(i.shortValue());
                String cmd = cmdMaps.get("1");
                commonCallbackMaps.get(cmd).statusCallback(deviceInfo);
            } else if (substring.equals("1000")){
                String time = "";
                //实时结果查询
                String idList = s.substring(40, 56);
                for (int i = 0; i < idList.length() / 2; i++) {
//                    log.info("日期：" + HexUtil.hexToInt(idList.substring(2*i,i*2+2)));
                    log.info("日期：" + Integer.parseInt(idList.substring(2*i,i*2+2)));
                    time += Integer.parseInt(idList.substring(2*i,i*2+2));
                }
                liveData.setDate(time);
                String s0 = s.substring(56, 60);
                String s01 = highToLow(s0);
                liveData.setCurrentValue(s01);
                log.info("电流有效值"+ stringToHex(s01));
                String s1 = s.substring(60, 64);
                String s11 = highToLow(s1);
                liveData.setTHDI(s11);
                log.info("THDi"+ stringToHex(s11));
                String s2 = s.substring(64, 68);
                String s21 = highToLow(s2);
                liveData.setTemperature(s21);
                log.info("温度"+ stringToHex(s21));
                String cmd = cmdMaps.get("2");
                commonCallbackMaps.get(cmd).statusCallback(liveData);
            } else if (substring.equals("1100")){
                //实时波形数据查询
                String idListLength = s.substring(40, 44);
                String idListDouble = s.substring(44, 48);
                String s1 = highToLow(idListLength);
                String s2 = highToLow(idListDouble);
                int length = HexUtil.hexToInt(s1);
                int times = HexUtil.hexToInt(s2);
                String idList = s.substring(48,length*4);
                String boData = "";
                for (int i = 0; i < idList.length()/4; i++) {
                    String idList0 = idList.substring(4*i,4*i+4);
                    String idList1 = highToLow(idList0);
                    short i1 = stringToHex(idList1);
                    boData += ((i1*1000)+"-");
                    log.info((i+1)+"个波形点为:"+(i1*times));
                }
                log.info(boData);
                webParam = boData;
                String cmd = cmdMaps.get("3");
                commonCallbackMaps.get(cmd).statusCallback(webParam);
            } else if (substring.equals("1200")) {
                //事件数据查询
                String idList = s.substring(40, 56);
            } else if (substring.equals("1300")) {
                //时间数据查询
                String idList = s.substring(40, 56);
                String time = "";
                for (int i = 0; i < (idList.length()-4)/2; i++) {
                    int temp = Integer.parseInt(idList.substring(2 * i, i * 2 + 2));
                    time += "-"+temp+"-";
                }
                String substring1 = idList.substring(14, 16);
                int i = HexUtil.hexToInt(substring1);
                time += i;
                log.info("时间"+time);
                webParam = time;
                String cmd = cmdMaps.get("5");
                commonCallbackMaps.get(cmd).statusCallback(webParam);
            } else if (substring.equals("1400")) {
                //通讯数据查询
                String idList = s.substring(40, 200);

//                String idListF = "";
//                for (int i = 0; i < idList.length()/4; i++) {
//                    String idList0 = idList.substring(4 * i, i * 4 + 4);
//                    String idList1 = highToLow(idList0);
//                    idListF += idList1;
//                }
//                String substring1 = idListF.substring(0, 50);
//                String substring2 = idListF.substring(50, 100);
//                String substring3 = idListF.substring(100, 160);

                String substring1 = idList.substring(0, 50);
                String substring2 = idList.substring(50, 100);
                String substring3 = idList.substring(100, 160);

                String s1 = stringToAscii(substring1);
                String s2 = stringToAscii(substring2);
                String s3 = stringToAscii(substring3);
                log.info("+CSQ:" + s1);
                log.info("+IMEI:" + s2);
                log.info("+ICCID:" + s3);
                webParam = s1 + s2 + s3;
                String cmd = cmdMaps.get("6");
                commonCallbackMaps.get(cmd).statusCallback(webParam);
            } else if (substring.equals("6500")) {
                //阈值定值查询
                String idList = s.substring(40, 52);
                String substring1 = idList.substring(0, 4);
                String s1 = highToLow(substring1);
                short i1 = stringToHex(s1);
                thresholdInfo.setValue(String.valueOf(i1));
                log.info("过流判断值" + i1 + "A");
                String substring2 = idList.substring(4, 8);
                String s2 = highToLow(substring2);
                short i2 = stringToHex(s2);
                thresholdInfo.setTime(String.valueOf(i2));
                log.info("过流判断时间" + i2 + "ms");
                String substring3 = idList.substring(4, 8);
                String s3 = highToLow(substring3);
                short i3 = stringToHex(s3);
                thresholdInfo.setInterval(String.valueOf(i3));
                log.info("通讯模块启动时间间隔" + i3 + "分钟");
                String cmd = cmdMaps.get("7");
                commonCallbackMaps.get(cmd).statusCallback(thresholdInfo);
            }
        }
    }
    public Map<String,CommonCallback<Object>> commonCallbackMaps = new ConcurrentHashMap<>();
    public Map<String,String> cmdMaps = new ConcurrentHashMap<>();
    @Override
    public void selectCmd(int id, int num, CommonCallback<Object> commonCallback){
        /* id 为 当前发往哪一个地方 num 为 选择指令 */
        /* id 16 0010  */
        String hexId = String.format("%04X", id);
        hexId = hexId.substring(2,4)+hexId.substring(0,2);
        log.info("+++++查看id++++" + hexId);
        String cmd,hexNum;
        switch (num){
//            # 1 0x01 设备信息 2 0x10 实时数据 3 0x11 实时波形数据 4 0x12 事件数据
//            # 5 0x13 时间数据 6 0x14 通讯数据 7 0x65 阈值定值
            case 1 -> {
                hexNum = "0100";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("1",cmd);
                sendCmd(hexId,cmd);
            }
            case 2 -> {
                hexNum = "1000";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("2",cmd);
                sendCmd(hexId,cmd);
            }
            case 3 -> {
                hexNum = "1100";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("3",cmd);
                sendCmd(hexId,cmd);
            }
            case 4 -> {
                hexNum = "1200";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("4",cmd);
                sendCmd(hexId,cmd);
            }
            case 5 -> {
                hexNum = "1300";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("5",cmd);
                sendCmd(hexId,cmd);
            }
            case 6 -> {
                hexNum = "1400";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("6",cmd);
                sendCmd(hexId,cmd);
            }
            case 7 -> {
                hexNum = "6500";
                cmd = APUPackageBuild.sendADUPCmd(hexId, hexNum);
                commonCallbackMaps.put(cmd,commonCallback);
                cmdMaps.put("7",cmd);
                sendCmd(hexId,cmd);
            }
            default -> log.info("输入未得到匹配");
        }
    }

    @Override
    public void sendWaterMeter1(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter1");
        sendCmd(id,cmd);
    }
    @Override
    public void sendWaterMeter2(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter2");
        sendCmd(id,cmd);
    }
    @Override
    public void sendWaterMeter3(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter3");
        sendCmd(id,cmd);
    }
    @Override
    public void sendWaterMeter4(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter4");
        sendCmd(id,cmd);
    }
    @Override
    public void sendWaterMeter5(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter5");
        sendCmd(id,cmd);
    }
    @Override
    public void sendWaterMeter6(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter6");
        sendCmd(id,cmd);
    }
    @Override
    public void sendWaterMeter7(String id){
        String cmd = PublicTools.getString("cmd", "electricityMeter7");
        sendCmd(id,cmd);
    }

    @Autowired
    public ThreadPoolTaskScheduler taskScheduler1;

    /**
     * 判断心跳是否在线
     */
    @Override
    public void getIpHeart(){
        taskScheduler1.scheduleWithFixedDelay(() -> {
            long l = System.currentTimeMillis();
            for (String s : ipMaps.keySet()) {
                long time = ipMaps.get(s).getTime();
                if (l-time >= 30){
                    ipMaps.remove(s);
                }
            }
        },59999);
    }
}
